package com.hnxxxy.system.Shiro;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;
/**
 * @author：张浩东
 * @Phone：15096207164
 * @QQ：1367048164
 * @E-mail：1367048164@qq.com
 * @date:2020-05-03 19:53
 */
@Configuration
public class ShiroConfig {

    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {

        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //关联Realm
        securityManager.setRealm((Realm) userRealm);
        return securityManager;
    }

    /**
     *  ShiroFilterFactoryBean处理拦截资源文件的问题
     */
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {

        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        //设置安全管理器securityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        /**
         * Shiro内置过滤器，可以实现权限相关的拦截器
         *    常用的过滤器：
         *       anon: 无需认证（登录）可以访问
         *       authc: 必须认证才可以访问
         *       logout: 执行后直接跳转 shiroFilterFactoryBean.setLoginUrl（）设置的URL
         *       user: 如果使用rememberMe的功能可以直接访问 user[]，表示必须纯在用户,当登入操作时不做检查
         *       perms： 该资源必须得到资源权限才可以访问 perms[user:add]表示需要某个或某些权限才能通过，
         *       多个参数时写 perms["user, admin"]，当有多个参数时必须每个参数都通过才算通过
         *       role: 该资源必须得到角色权限才可以访问，表示需要某个或某些角色才能通过，多个参数roles["",""]
         */
        Map<String, String> filterMap = new LinkedHashMap<String, String>();

        //允许访问静态资源
        filterMap.put("/logout", "logout");
        filterMap.put("/layui/**", "anon");
        filterMap.put("/getGifCode", "anon");
        filterMap.put("/ajaxLogin", "anon");
        filterMap.put("/userUpdate1", "anon");
        filterMap.put("/userUpdate2", "anon");
        filterMap.put("/userUpdate3", "anon");
        filterMap.put("/register", "anon");
        filterMap.put("/register/a", "anon");
        filterMap.put("/backstage", "anon");

        filterMap.put("/communityList", "anon");
        filterMap.put("/activityList", "anon");
        filterMap.put("/addcommunity", "anon");
        filterMap.put("/addactivity", "anon");
        filterMap.put("/mycommunity", "anon");

        filterMap.put("/u/**", "anon");
        filterMap.put("/f/**", "anon");
        filterMap.put("/b/**", "anon");
        filterMap.put("/assets/**", "anon");
        filterMap.put("/css/**", "anon");
        filterMap.put("/images/**", "anon");
        filterMap.put("/img/**", "anon");
        filterMap.put("/js/**", "anon");
        filterMap.put("/", "anon");


        // 配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了

//        // 这里自定义的权限拦截规则
        filterMap.put("/main/login", "authc");
        filterMap.put("/backstage", "authc");

        //拦截其他所有，必须写最后
        filterMap.put("/**", "authc");

        //设置登录URL
        shiroFilterFactoryBean.setLoginUrl("/login");
        //设置无权限时跳转的URL
        shiroFilterFactoryBean.setUnauthorizedUrl("/error");
        //登录成功后要跳转的链接
        shiroFilterFactoryBean.setSuccessUrl("/backstage");

        //注入filterMap设置
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
        return shiroFilterFactoryBean;
    }

    /**
     * 创建Realm
     */
    @Bean(name = "userRealm")
    public UserRealm getRealm(@Qualifier("hashMatch") HashedCredentialsMatcher hashedCredentialsMatcher) {
        UserRealm userRealm = new UserRealm();
        userRealm.setCredentialsMatcher(hashedCredentialsMatcher);
        return userRealm;
    }


    /**
     * 配置ShiroDialect，用于thymeleaf和shiro标签配合使用
     */
    @Bean
    public ShiroDialect getShiroDialect() {
        return new ShiroDialect();
    }


    /**
     * 开启aop注解支持
     * //     * @param advisorAutoProxyCreator
     *
     * @return
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }

    /**
     * 开启aop注解支持
     *
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }


    /*加密*/
    @Bean("hashMatch")
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        credentialsMatcher.setHashAlgorithmName("MD5");
        credentialsMatcher.setHashIterations(1000);
//        //此处的设置，true加密用的hex编码，false用的base64编码
//        credentialsMatcher.setStoredCredentialsHexEncoded(false);
        return credentialsMatcher;
    }

//
//    /**
//     * redisManager
//     *
//     * @return
//     */
//    public RedisManager redisManager() {
//        RedisManager redisManager = new RedisManager();
//        redisManager.setHost("127.0.0.1");
//        redisManager.setPort(6379);
//        redisManager.setExpire(1800);// 配置缓存过期时间30FEN
//        redisManager.setTimeout(0);
//        return redisManager;
//    }
//
//    /**
//     * cacheManager
//     *
//     * @return
//     */
//    public RedisCacheManager cacheManager() {
//        RedisCacheManager redisCacheManager = new RedisCacheManager();
//        redisCacheManager.setRedisManager(redisManager());
//        return redisCacheManager;
//    }
//
//    /**
//     * redisSessionDAO
//     */
//    public RedisSessionDAO redisSessionDAO() {
//        RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
//        redisSessionDAO.setRedisManager(redisManager());
//        return redisSessionDAO;
//    }
//
//    /**
//     * sessionManager
//     */
//    public DefaultWebSessionManager SessionManager() {
//        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
//        sessionManager.setSessionDAO(redisSessionDAO());
//        return sessionManager;
//    }

    /**
     * Shiro生命周期处理器
     */
    @Bean
    public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

}
